Major cleanup, added support for 32 bpp and 4 bpp (uncompressed) images,
authorArjan van de Ven <arjan@fenrus.demon.nl>
Sat, 4 Dec 1999 18:17:52 +0000 (18:17 +0000)
committerArjan van de Ven <arjan@src.gnome.org>
Sat, 4 Dec 1999 18:17:52 +0000 (18:17 +0000)
1999-12-04  Arjan van de Ven <arjan@fenrus.demon.nl>

* gdk-pixbuf/io-bmp.c: Major cleanup, added support for
32 bpp and 4 bpp (uncompressed) images, fixed 1bpp.

* gdk-pixbuf/io-ras.c: Minor cleanup, ran through lclint

* gdk-pixbuf/io-ico.c: Minor cleanup, fixed 1bpp icons,
  ran through lclint.

* gdk-pixbuf/gdk-pixbuf-io.c: Added detection of .CUR files
(Windows Cursor files). These are identical to .ICO files,
except for the signature and 2 extra fields for the hotspot.

gdk-pixbuf/ChangeLog
gdk-pixbuf/gdk-pixbuf-io.c
gdk-pixbuf/io-bmp.c
gdk-pixbuf/io-ico.c
gdk-pixbuf/io-ras.c

index 2f51bd106481574f1a8422b16ca45fed293b123e..a6adbec11b5af49f2eef1c48c9a400679928d470 100644 (file)
@@ -1,3 +1,17 @@
+1999-12-04  Arjan van de Ven <arjan@fenrus.demon.nl>
+
+       * gdk-pixbuf/io-bmp.c: Major cleanup, added support for
+       32 bpp and 4 bpp (uncompressed) images, fixed 1bpp.
+       
+       * gdk-pixbuf/io-ras.c: Minor cleanup, ran through lclint
+
+       * gdk-pixbuf/io-ico.c: Minor cleanup, fixed 1bpp icons,
+       ran through lclint.
+
+       * gdk-pixbuf/gdk-pixbuf-io.c: Added detection of .CUR files
+       (Windows Cursor files). These are identical to .ICO files, 
+       except for the signature and 2 extra fields for the hotspot.
+
 1999-12-03  Jonathan Blandford  <jrb@redhat.com>
 
        * gdk-pixbuf/io-gif.c (gif_fill_in_lines): added a comment to
index 6f09ec2fde2c23bc8efa050adfc58d4f51b0bb1b..ad311401d01242e5bdb16ac195b5a6a13ab96be1 100644 (file)
@@ -145,7 +145,7 @@ pixbuf_check_ico (guchar *buffer, int size)
                return FALSE;
        if (buffer [0] != 0x0 ||
            buffer [1] != 0x0 ||
-           buffer [2] != 0x1 ||
+           ((buffer [2] != 0x1)&&(buffer[2]!=0x2)) ||
            buffer [3] != 0x0 ||
            buffer [5] != 0x0 )
                return FALSE;
index 469288c4b0184a715ec093dfd56705b2c5c2b580..339395b67c66b085f09bb36e364f4c9bf9783917 100644 (file)
 /*
 
 Known bugs:
-       * Compressed files don't work yet
-       * bi-tonal files aren't tested 
+       * 4bpp compressed files don't work
+       * bi-tonal files aren't tested with palettes
 
 */
 
 #include <config.h>
 #include <stdio.h>
 #include <unistd.h>
-#include "gdk-pixbuf.h"
-#include "gdk-pixbuf-io.h"
-
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gdk-pixbuf/gdk-pixbuf-io.h>
 \f
 
 
-struct headerpair {
-       guint width;
-       guint height;
-       guint depth;
-       guint Negative;         /* Negative = 1 -> top down BMP,  
-                                  Negative = 0 -> bottom up BMP */
-};
+
 
 /* 
 
 These structures are actually dummies. These are according to
-the "Windows API reference guide volume II" as written by Borland,
-but GCC fiddles with the alignment of the internal members.
+the "Windows API reference guide volume II" as written by 
+Borland International, but GCC fiddles with the alignment of 
+the internal members, so these aren't actually usable.
 
 */
 
@@ -77,57 +71,56 @@ struct BitmapInfoHeader {
        guint biClrImportant;
 };
 
+/* 
+
+DumpBIH printf's the values in a BitmapInfoHeader to the screen, for 
+debugging purposes.
+
+*/
+#if DUMPBIH
 static void DumpBIH(unsigned char *BIH)
-{                              /* For debugging */
+{                              
        printf("biSize      = %i \n",
-              (BIH[3] << 24) + (BIH[2] << 16) + (BIH[1] << 8) + (BIH[0]));
+              (int) (BIH[3] << 24) + (BIH[2] << 16) + (BIH[1] << 8) +
+              (BIH[0]));
        printf("biWidth     = %i \n",
-              (BIH[7] << 24) + (BIH[6] << 16) + (BIH[5] << 8) + (BIH[4]));
+              (int) (BIH[7] << 24) + (BIH[6] << 16) + (BIH[5] << 8) +
+              (BIH[4]));
        printf("biHeight    = %i \n",
-              (BIH[11] << 24) + (BIH[10] << 16) + (BIH[9] << 8) +
+              (int) (BIH[11] << 24) + (BIH[10] << 16) + (BIH[9] << 8) +
               (BIH[8]));
-       printf("biPlanes    = %i \n", (BIH[13] << 8) + (BIH[12]));
-       printf("biBitCount  = %i \n", (BIH[15] << 8) + (BIH[14]));
+       printf("biPlanes    = %i \n", (int) (BIH[13] << 8) + (BIH[12]));
+       printf("biBitCount  = %i \n", (int) (BIH[15] << 8) + (BIH[14]));
        printf("biCompress  = %i \n",
-              (BIH[19] << 24) + (BIH[18] << 16) + (BIH[17] << 8) +
+              (int) (BIH[19] << 24) + (BIH[18] << 16) + (BIH[17] << 8) +
               (BIH[16]));
        printf("biSizeImage = %i \n",
-              (BIH[23] << 24) + (BIH[22] << 16) + (BIH[21] << 8) +
+              (int) (BIH[23] << 24) + (BIH[22] << 16) + (BIH[21] << 8) +
               (BIH[20]));
        printf("biXPels     = %i \n",
-              (BIH[27] << 24) + (BIH[26] << 16) + (BIH[25] << 8) +
+              (int) (BIH[27] << 24) + (BIH[26] << 16) + (BIH[25] << 8) +
               (BIH[24]));
        printf("biYPels     = %i \n",
-              (BIH[31] << 24) + (BIH[30] << 16) + (BIH[29] << 8) +
+              (int) (BIH[31] << 24) + (BIH[30] << 16) + (BIH[29] << 8) +
               (BIH[28]));
        printf("biClrUsed   = %i \n",
-              (BIH[35] << 24) + (BIH[34] << 16) + (BIH[33] << 8) +
+              (int) (BIH[35] << 24) + (BIH[34] << 16) + (BIH[33] << 8) +
               (BIH[32]));
        printf("biClrImprtnt= %i \n",
-              (BIH[39] << 24) + (BIH[38] << 16) + (BIH[37] << 8) +
+              (int) (BIH[39] << 24) + (BIH[38] << 16) + (BIH[37] << 8) +
               (BIH[36]));
 }
+#endif
+/* struct headerpair contains the decoded width/height/depth info for
+   the current bitmap */
 
-/* 
-       This does a byte-order swap. Does glib have something like
-       be32_to_cpu() ??
-*/
-
-static unsigned int le32_to_cpu(guint i)
-{
-       unsigned int i2;
-       return i2;
-}
-
-/* 
-       Destroy notification function for the libart pixbuf 
-*/
-
-static void free_buffer(gpointer user_data, gpointer data)
-{
-       free(data);
-}
-
+struct headerpair {
+       guint width;
+       guint height;
+       guint depth;
+       guint Negative;         /* Negative = 1 -> top down BMP,  
+                                  Negative = 0 -> bottom up BMP */
+};
 
 /* Data needed for the "state" during decompression */
 struct bmp_compression_state {
@@ -161,8 +154,10 @@ struct bmp_progressive_state {
        gint Lines;             /* # of finished lines */
 
        gint Type;              /*  
+                                  32 = RGB + alpha
                                   24 = RGB
-                                  8 = 8 bit colormapped
+                                  4  = 4 bpp colormapped
+                                  8  = 8 bpp colormapped
                                   1  = 1 bit bitonal 
                                 */
        gint Compressed;
@@ -183,13 +178,13 @@ gboolean image_load_increment(gpointer data, guchar * buf, guint size);
 
 
 
-/* Shared library entry point */
+/* Shared library entry point --> This should be removed when
+   generic_image_load enters gdk-pixbuf-io. */
 GdkPixbuf *image_load(FILE * f)
 {
        guchar *membuf;
        size_t length;
        struct bmp_progressive_state *State;
-       int fd;
 
        GdkPixbuf *pb;
 
@@ -202,7 +197,7 @@ GdkPixbuf *image_load(FILE * f)
        while (feof(f) == 0) {
                length = fread(membuf, 1, 4096, f);
                if (length > 0)
-                       image_load_increment(State, membuf, length);
+                       (void) image_load_increment(State, membuf, length);
 
        }
        g_free(membuf);
@@ -212,31 +207,38 @@ GdkPixbuf *image_load(FILE * f)
        pb = State->pixbuf;
 
        image_stop_load(State);
-       return State->pixbuf;
+       return pb;
 }
 
 static void DecodeHeader(unsigned char *BFH, unsigned char *BIH,
                         struct bmp_progressive_state *State)
 {
-/*     DumpBIH(BIH);*/
+#if DUMPBIH
+       DumpBIH(BIH);
+#endif
+
        State->Header.width =
-           (BIH[7] << 24) + (BIH[6] << 16) + (BIH[5] << 8) + (BIH[4]);
+           (int) (BIH[7] << 24) + (BIH[6] << 16) + (BIH[5] << 8) +
+           (BIH[4]);
        State->Header.height =
-           (BIH[11] << 24) + (BIH[10] << 16) + (BIH[9] << 8) + (BIH[8]);
-       State->Header.depth = (BIH[15] << 8) + (BIH[14]);;
+           (int) (BIH[11] << 24) + (BIH[10] << 16) + (BIH[9] << 8) +
+           (BIH[8]);
+       State->Header.depth = (int) (BIH[15] << 8) + (BIH[14]);;
 
        State->Type = State->Header.depth;      /* This may be less trivial someday */
        State->HeaderSize =
-           ((BFH[13] << 24) + (BFH[12] << 16) + (BFH[11] << 8) +
-            (BFH[10]));
-       if (State->HeaderSize >= 14 + 40 + 768 + 512)
-               State->HeaderSize = 14 + 40 + 768 + 512 - 1;
+           (int) ((BFH[13] << 24) + (BFH[12] << 16) + (BFH[11] << 8) +
+                  (BFH[10]));
+       if (State->HeaderSize >= 14 + 40 + 1024)
+               State->HeaderBuf =
+                   g_realloc(State->HeaderBuf, State->HeaderSize);
 
        if ((BIH[16] != 0) || (BIH[17] != 0) || (BIH[18] != 0)
            || (BIH[19] != 0)) {
                State->Compressed = 1;
        }
 
+       /* Negative heights indicates bottom-down pixelorder */
        if (State->Header.height < 0) {
                State->Header.height = -State->Header.height;
                State->Header.Negative = 1;
@@ -246,10 +248,14 @@ static void DecodeHeader(unsigned char *BFH, unsigned char *BIH,
                State->Header.Negative = 0;
        }
 
+       if (State->Type == 32)
+               State->LineWidth = State->Header.width * 4;
        if (State->Type == 24)
                State->LineWidth = State->Header.width * 3;
        if (State->Type == 8)
                State->LineWidth = State->Header.width * 1;
+       if (State->Type == 4)
+               State->LineWidth = (State->Header.width + 1) / 2;
        if (State->Type == 1) {
                State->LineWidth = State->Header.width / 8;
                if ((State->Header.width & 7) != 0)
@@ -268,10 +274,16 @@ static void DecodeHeader(unsigned char *BFH, unsigned char *BIH,
 
 
        if (State->pixbuf == NULL) {
-               State->pixbuf =
-                   gdk_pixbuf_new(ART_PIX_RGB, FALSE, 8,
-                                  (gint) State->Header.width,
-                                  (gint) State->Header.height);
+               if (State->Type == 32)
+                       State->pixbuf =
+                           gdk_pixbuf_new(ART_PIX_RGB, TRUE, 8,
+                                          (gint) State->Header.width,
+                                          (gint) State->Header.height);
+               else
+                       State->pixbuf =
+                           gdk_pixbuf_new(ART_PIX_RGB, FALSE, 8,
+                                          (gint) State->Header.width,
+                                          (gint) State->Header.height);
 
                if (State->prepared_func != NULL)
                        /* Notify the client that we are ready to go */
@@ -300,8 +312,10 @@ image_begin_load(ModulePreparedNotifyFunc prepared_func,
        context->user_data = user_data;
 
        context->HeaderSize = 54;
-       context->HeaderBuf = g_malloc(14 + 40 + 768 + 512);
-       /* 768 for the colormap */
+       context->HeaderBuf = g_malloc(14 + 40 + 1024);
+       /* 14 for the BitmapFileHeader, 40 for the BitmapImageHeader and 
+          1024 for the colormap */
+
        context->HeaderDone = 0;
 
        context->LineWidth = 0;
@@ -337,8 +351,10 @@ void image_stop_load(gpointer data)
        if (context->LineBuf != NULL)
                g_free(context->LineBuf);
        context->LineBuf = NULL;
+
        if (context->HeaderBuf != NULL)
                g_free(context->HeaderBuf);
+       context->LineBuf = NULL;
 
        if (context->pixbuf)
                gdk_pixbuf_unref(context->pixbuf);
@@ -347,6 +363,34 @@ void image_stop_load(gpointer data)
 }
 
 
+/*
+The OneLineXX functions are called when 1 line worth of data is present.
+OneLine24 is the 24 bpp-version.
+*/
+static void OneLine32(struct bmp_progressive_state *context)
+{
+       gint X;
+       guchar *Pixels;
+
+       X = 0;
+       if (context->Header.Negative == 0)
+               Pixels = context->pixbuf->art_pixbuf->pixels +
+                   gdk_pixbuf_get_rowstride(context->pixbuf) *
+                   (context->Header.height - context->Lines - 1);
+       else
+               Pixels = context->pixbuf->art_pixbuf->pixels +
+                   gdk_pixbuf_get_rowstride(context->pixbuf) *
+                   context->Lines;
+       while (X < context->Header.width) {
+               Pixels[X * 4 + 0] = context->LineBuf[X * 4 + 2];
+               Pixels[X * 4 + 1] = context->LineBuf[X * 4 + 1];
+               Pixels[X * 4 + 2] = context->LineBuf[X * 4 + 0];
+               Pixels[X * 4 + 3] = context->LineBuf[X * 4 + 3];
+               X++;
+       }
+
+}
+
 static void OneLine24(struct bmp_progressive_state *context)
 {
        gint X;
@@ -385,7 +429,6 @@ static void OneLine8(struct bmp_progressive_state *context)
                    gdk_pixbuf_get_rowstride(context->pixbuf) *
                    context->Lines;
        while (X < context->Header.width) {
-               /* The joys of having a BGR byteorder */
                Pixels[X * 3 + 0] =
                    context->HeaderBuf[4 * context->LineBuf[X] + 56];
                Pixels[X * 3 + 1] =
@@ -396,6 +439,47 @@ static void OneLine8(struct bmp_progressive_state *context)
        }
 }
 
+static void OneLine4(struct bmp_progressive_state *context)
+{
+       gint X;
+       guchar *Pixels;
+
+       X = 0;
+       if (context->Header.Negative == 0)
+               Pixels = context->pixbuf->art_pixbuf->pixels +
+                   gdk_pixbuf_get_rowstride(context->pixbuf) *
+                   (context->Header.height - context->Lines - 1);
+       else
+               Pixels = context->pixbuf->art_pixbuf->pixels +
+                   gdk_pixbuf_get_rowstride(context->pixbuf) *
+                   context->Lines;
+
+       while (X < context->Header.width) {
+               guchar Pix;
+
+               Pix = context->LineBuf[X / 2];
+
+               Pixels[X * 3 + 0] =
+                   context->HeaderBuf[4 * (Pix >> 4) + 56];
+               Pixels[X * 3 + 1] =
+                   context->HeaderBuf[4 * (Pix >> 4) + 55];
+               Pixels[X * 3 + 2] =
+                   context->HeaderBuf[4 * (Pix >> 4) + 54];
+               X++;
+               if (X < context->Header.width) {
+                       /* Handle the other 4 bit pixel only when there is one */
+                       Pixels[X * 3 + 0] =
+                           context->HeaderBuf[4 * (Pix & 15) + 56];
+                       Pixels[X * 3 + 1] =
+                           context->HeaderBuf[4 * (Pix & 15) + 55];
+                       Pixels[X * 3 + 2] =
+                           context->HeaderBuf[4 * (Pix & 15) + 54];
+                       X++;
+               }
+       }
+
+}
+
 static void OneLine1(struct bmp_progressive_state *context)
 {
        gint X;
@@ -411,14 +495,13 @@ static void OneLine1(struct bmp_progressive_state *context)
                    gdk_pixbuf_get_rowstride(context->pixbuf) *
                    context->Lines;
        while (X < context->Header.width) {
-               int Bit;
+               gint Bit;
 
                Bit = (context->LineBuf[X / 8]) >> (7 - (X & 7));
                Bit = Bit & 1;
-               /* The joys of having a BGR byteorder */
-               Pixels[X * 3 + 0] = context->HeaderBuf[Bit + 32];
-               Pixels[X * 3 + 1] = context->HeaderBuf[Bit + 2 + 32];
-               Pixels[X * 3 + 2] = context->HeaderBuf[Bit + 4 + 32];
+               Pixels[X * 3 + 0] = Bit*255;
+               Pixels[X * 3 + 1] = Bit*255;
+               Pixels[X * 3 + 2] = Bit*255;
                X++;
        }
 }
@@ -430,10 +513,14 @@ static void OneLine(struct bmp_progressive_state *context)
        if (context->Lines >= context->Header.height)
                return;
 
+       if (context->Type == 32)
+               OneLine32(context);
        if (context->Type == 24)
                OneLine24(context);
        if (context->Type == 8)
                OneLine8(context);
+       if (context->Type == 4)
+               OneLine4(context);
        if (context->Type == 1)
                OneLine1(context);
 
@@ -450,6 +537,113 @@ static void OneLine(struct bmp_progressive_state *context)
        }
 }
 
+/* DoCompressedByte handles 1 byte of incomming compressed data */
+void DoCompressedByte(struct bmp_progressive_state *context, guchar ** buf,
+                     gint * size)
+{
+       gint BytesToCopy;
+       switch (context->compr.phase) {
+       case 0:         /* Neutral state */
+               if (buf[0] != 0) {      /* run count */
+                       context->compr.phase = 1;
+                       context->compr.RunCount = (*buf)[0];
+               } else {        /* Escape */
+                       context->compr.phase = 2;
+               }
+               (*buf)++;
+               (*size)--;
+               break;
+       case 1:         /* Run count received.... */
+               while (context->compr.RunCount > 0) {
+                       BytesToCopy =
+                           context->LineWidth - context->LineDone;
+                       if (BytesToCopy > context->compr.RunCount)
+                               BytesToCopy = context->compr.RunCount;
+                       if (BytesToCopy > 0) {
+                               memset(context->LineBuf +
+                                      context->LineDone,
+                                      (*buf)[0], BytesToCopy);
+
+                               context->compr.RunCount -= BytesToCopy;
+                               context->LineDone += BytesToCopy;
+                       }
+                       if ((context->LineDone >= context->LineWidth)
+                           && (context->LineWidth > 0)) {
+                               OneLine(context);
+                       }
+               }
+               context->compr.phase = 0;
+               (*buf)++;
+               (*size)--;
+               break;
+       case 2:         /* Escape received */
+               if ((*buf)[0] == 0) {   /* End of line */
+                       context->compr.phase = 0;
+                       if (context->LineDone > 0)
+                               OneLine(context);
+               } else if ((*buf)[0] == 1) {    /* End of image */
+                       OneLine(context);
+                       context->compr.phase = 6;
+                       (*size) = 0;
+                       break;
+               } else if ((*buf)[0] == 2) {    /* Cursor displacement */
+                       context->compr.phase = 4;
+               } else {
+                       context->compr.phase = 3;
+                       context->compr.RunCount = (*buf)[0];
+               }
+               (*buf)++;
+               (*size)--;
+
+               break;
+       case 3:
+               while ((context->compr.RunCount > 0)
+                      && (size > 0)) {
+                       BytesToCopy =
+                           context->LineWidth - context->LineDone;
+                       if (BytesToCopy > context->compr.RunCount)
+                               BytesToCopy = context->compr.RunCount;
+                       if (BytesToCopy > *size)
+                               BytesToCopy = *size;
+
+                       if (BytesToCopy > 0) {
+                               memcpy(context->LineBuf +
+                                      context->LineDone,
+                                      *buf, BytesToCopy);
+
+                               context->compr.RunCount -= BytesToCopy;
+                               (*buf) += BytesToCopy;
+                               (*size) -= BytesToCopy;
+                               context->LineDone += BytesToCopy;
+                       }
+                       if ((context->LineDone >= context->LineWidth)
+                           && (context->LineWidth > 0))
+                               OneLine(context);
+               }
+               if (context->compr.RunCount <= 0)
+                       context->compr.phase = 0;
+
+               break;
+       case 4:
+               context->compr.phase = 5;
+               context->compr.XDelta = (*buf)[0];
+               (*buf)++;
+               (*size)--;
+               break;
+       case 5:
+               context->compr.phase = 0;
+               context->compr.YDelta = (*buf)[0];
+               g_assert(0);    /* No implementatio of this yet */
+               /* If this happens, please email me (arjan@fenrus.demon.nl)
+                  the image concerned. */
+               (*buf)++;
+               (*size)--;
+               break;
+       case 6:
+               (*size) = 0;
+       }
+}
+
 /*
  * context - from image_begin_load
  * buf - new image data
@@ -473,7 +667,7 @@ gboolean image_load_increment(gpointer data, guchar * buf, guint size)
                        if (BytesToCopy > size)
                                BytesToCopy = size;
 
-                       memcpy(context->HeaderBuf + context->HeaderDone,
+                       memmove(context->HeaderBuf + context->HeaderDone,
                               buf, BytesToCopy);
 
                        size -= BytesToCopy;
@@ -481,132 +675,18 @@ gboolean image_load_increment(gpointer data, guchar * buf, guint size)
                        context->HeaderDone += BytesToCopy;
 
                } else if (context->Compressed) {
-                       /* Compression is done 1 at a time for now */
-                       switch (context->compr.phase) {
-                       case 0:
-                               if (buf[0] != 0) {      /* run count */
-                                       context->compr.phase = 1;
-                                       context->compr.RunCount = buf[0];
-                               } else {        /* Escape */
-                                       context->compr.phase = 2;
-                               }
-                               buf++;
-                               size--;
-                               break;
-                       case 1: /* Run count received.... */
-                               while (context->compr.RunCount > 0) {
-                                       BytesToCopy =
-                                           context->LineWidth -
-                                           context->LineDone;
-                                       if (BytesToCopy >
-                                           context->compr.
-                                           RunCount) BytesToCopy =
-                                                   context->compr.
-                                                   RunCount;
-                                       if (BytesToCopy > 0) {
-                                               memset(context->LineBuf +
-                                                      context->LineDone,
-                                                      buf[0],
-                                                      BytesToCopy);
-
-                                               context->compr.RunCount -=
-                                                   BytesToCopy;
-                                               context->LineDone +=
-                                                   BytesToCopy;
-                                       }
-                                       if (
-                                           (context->LineDone >=
-                                            context->LineWidth)
-                                           && (context->LineWidth > 0)) {
-                                               OneLine(context);
-                                       }
-                               }
-                               context->compr.phase = 0;
-                               buf++;
-                               size--;
-                               break;
-                       case 2: /* Escape received */
-                               if (buf[0] == 0) {      /* End of line */
-                                       context->compr.phase = 0;
-                                       if (context->LineDone > 0)
-                                               OneLine(context);
-                               } else if (buf[0] == 1) {       /* End of image */
-                                       OneLine(context);
-                                       context->compr.phase = 6;
-                                       size = 0;
-                                       break;
-                               } else if (buf[0] == 2) {       /* Cursor displacement */
-                                       context->compr.phase = 4;
-                               } else {
-                                       context->compr.phase = 3;
-                                       context->compr.RunCount = buf[0];
-                               }
-                               buf++;
-                               size--;
-
-                               break;
-                       case 3:
-                               while ((context->compr.RunCount > 0)
-                                      && (size > 0)) {
-                                       BytesToCopy =
-                                           context->LineWidth -
-                                           context->LineDone;
-                                       if (BytesToCopy >
-                                           context->compr.
-                                           RunCount) BytesToCopy =
-                                                   context->compr.
-                                                   RunCount;
-                                       if (BytesToCopy > size)
-                                               BytesToCopy = size;
-
-                                       if (BytesToCopy > 0) {
-                                               memcpy(context->LineBuf +
-                                                      context->LineDone,
-                                                      buf, BytesToCopy);
-
-                                               context->compr.RunCount -=
-                                                   BytesToCopy;
-                                               buf += BytesToCopy;
-                                               size -= BytesToCopy;
-                                               context->LineDone +=
-                                                   BytesToCopy;
-                                       }
-                                       if (
-                                           (context->LineDone >=
-                                            context->LineWidth)
-                                           && (context->LineWidth > 0))
-                                               OneLine(context);
-                               }
-                               if (context->compr.RunCount <= 0)
-                                       context->compr.phase = 0;
-
-                               break;
-                       case 4:
-                               context->compr.phase = 5;
-                               context->compr.XDelta = buf[0];
-                               buf++;
-                               size--;
-                               break;
-                       case 5:
-                               context->compr.phase = 0;
-                               context->compr.YDelta = buf[0];
-                               g_assert(0);    /* No implementatio of this yet */
-                               buf++;
-                               size--;
-                               break;
-                       case 6:
-                               size = 0;
-                       }
+                       /* Compression is done 1 byte at a time for now */
+                       DoCompressedByte(context, &buf, &size);
 
                } else {
-                       /* Pixeldata only */
+                       /* Uncompressed pixeldata */
                        BytesToCopy =
                            context->LineWidth - context->LineDone;
                        if (BytesToCopy > size)
                                BytesToCopy = size;
 
                        if (BytesToCopy > 0) {
-                               memcpy(context->LineBuf +
+                               memmove(context->LineBuf +
                                       context->LineDone, buf,
                                       BytesToCopy);
 
index 002f3310e6e86262259b8a0cf17aec66ed76152c..b7719a795f1fb555c66ef63945767635216d8c0c 100644 (file)
@@ -1,4 +1,4 @@
-/* GdkPixbuf library - Windows Bitmap image loader
+/* GdkPixbuf library - Windows Icon/Cursor image loader
  *
  * Copyright (C) 1999 The Free Software Foundation
  *
@@ -23,6 +23,7 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#undef DUMPBIH
 /*
 
 Icons are just like BMP's, except for the header.
@@ -40,19 +41,13 @@ Known bugs:
 \f
 
 
-struct headerpair {
-       guint width;
-       guint height;
-       guint depth;
-       guint Negative;         /* Negative = 1 -> top down BMP,  
-                                  Negative = 0 -> bottom up BMP */
-};
 
 /* 
 
 These structures are actually dummies. These are according to
-the "Windows API reference guide volume II" as written by Borland,
-but GCC fiddles with the alignment of the internal members.
+the "Windows API reference guide volume II" as written by 
+Borland International, but GCC fiddles with the alignment of
+the internal members.
 
 */
 
@@ -77,59 +72,53 @@ struct BitmapInfoHeader {
        guint biClrImportant;
 };
 
+#ifdef DUMPBIH
+/* 
+
+DumpBIH printf's the values in a BitmapInfoHeader to the screen, for 
+debugging purposes.
+
+*/
 static void DumpBIH(unsigned char *BIH)
-{                              /* For debugging */
+{                              
        printf("biSize      = %i \n",
-              (BIH[3] << 24) + (BIH[2] << 16) + (BIH[1] << 8) + (BIH[0]));
+              (int)(BIH[3] << 24) + (BIH[2] << 16) + (BIH[1] << 8) + (BIH[0]));
        printf("biWidth     = %i \n",
-              (BIH[7] << 24) + (BIH[6] << 16) + (BIH[5] << 8) + (BIH[4]));
+              (int)(BIH[7] << 24) + (BIH[6] << 16) + (BIH[5] << 8) + (BIH[4]));
        printf("biHeight    = %i \n",
-              (BIH[11] << 24) + (BIH[10] << 16) + (BIH[9] << 8) +
+              (int)(BIH[11] << 24) + (BIH[10] << 16) + (BIH[9] << 8) +
               (BIH[8]));
-       printf("biPlanes    = %i \n", (BIH[13] << 8) + (BIH[12]));
-       printf("biBitCount  = %i \n", (BIH[15] << 8) + (BIH[14]));
+       printf("biPlanes    = %i \n", (int)(BIH[13] << 8) + (BIH[12]));
+       printf("biBitCount  = %i \n", (int)(BIH[15] << 8) + (BIH[14]));
        printf("biCompress  = %i \n",
-              (BIH[19] << 24) + (BIH[18] << 16) + (BIH[17] << 8) +
+              (int)(BIH[19] << 24) + (BIH[18] << 16) + (BIH[17] << 8) +
               (BIH[16]));
        printf("biSizeImage = %i \n",
-              (BIH[23] << 24) + (BIH[22] << 16) + (BIH[21] << 8) +
+              (int)(BIH[23] << 24) + (BIH[22] << 16) + (BIH[21] << 8) +
               (BIH[20]));
        printf("biXPels     = %i \n",
-              (BIH[27] << 24) + (BIH[26] << 16) + (BIH[25] << 8) +
+              (int)(BIH[27] << 24) + (BIH[26] << 16) + (BIH[25] << 8) +
               (BIH[24]));
        printf("biYPels     = %i \n",
-              (BIH[31] << 24) + (BIH[30] << 16) + (BIH[29] << 8) +
+              (int)(BIH[31] << 24) + (BIH[30] << 16) + (BIH[29] << 8) +
               (BIH[28]));
        printf("biClrUsed   = %i \n",
-              (BIH[35] << 24) + (BIH[34] << 16) + (BIH[33] << 8) +
+              (int)(BIH[35] << 24) + (BIH[34] << 16) + (BIH[33] << 8) +
               (BIH[32]));
        printf("biClrImprtnt= %i \n",
-              (BIH[39] << 24) + (BIH[38] << 16) + (BIH[37] << 8) +
+              (int)(BIH[39] << 24) + (BIH[38] << 16) + (BIH[37] << 8) +
               (BIH[36]));
 }
-
-/* 
-       This does a byte-order swap. Does glib have something like
-       be32_to_cpu() ??
-*/
-
-static unsigned int le32_to_cpu(guint i)
-{
-       unsigned int i2;
-       return i2;
-}
-
-/* 
-       Destroy notification function for the libart pixbuf 
-*/
-
-static void free_buffer(gpointer user_data, gpointer data)
-{
-       free(data);
-}
-
+#endif
 
 /* Progressive loading */
+struct headerpair {
+       guint width;
+       guint height;
+       guint depth;
+       guint Negative;         /* Negative = 1 -> top down BMP,  
+                                  Negative = 0 -> bottom up BMP */
+};
 
 struct ico_progressive_state {
        ModulePreparedNotifyFunc prepared_func;
@@ -170,13 +159,13 @@ gboolean image_load_increment(gpointer data, guchar * buf, guint size);
 
 
 
-/* Shared library entry point */
+/* Shared library entry point --> Can go when generic_image_load
+   enters gdk-pixbuf-io */
 GdkPixbuf *image_load(FILE * f)
 {
        guchar *membuf;
        size_t length;
        struct ico_progressive_state *State;
-       int fd;
 
        GdkPixbuf *pb;
 
@@ -189,7 +178,7 @@ GdkPixbuf *image_load(FILE * f)
        while (feof(f) == 0) {
                length = fread(membuf, 1, 4096, f);
                if (length > 0)
-                       image_load_increment(State, membuf, length);
+                       (void)image_load_increment(State, membuf, length);
 
        }
        g_free(membuf);
@@ -199,7 +188,7 @@ GdkPixbuf *image_load(FILE * f)
        pb = State->pixbuf;
 
        image_stop_load(State);
-       return State->pixbuf;
+       return pb;
 }
 
 static void DecodeHeader(guchar *Data, gint Bytes,
@@ -220,7 +209,6 @@ static void DecodeHeader(guchar *Data, gint Bytes,
  
        IconCount = (Data[5] << 8) + (Data[4]);
  
-/*     printf("There are %i icons in this file \n",IconCount);*/
        State->HeaderSize = 6 + IconCount*16;
        
        if (State->HeaderSize>State->BytesInHeaderBuf) {
@@ -244,21 +232,17 @@ static void DecodeHeader(guchar *Data, gint Bytes,
                ThisHeight = Ptr[1];
                ThisColors = (Ptr[2]);
                if (ThisColors==0) 
-                       ThisColors=256; /* Yes, this is in the spec */
+                       ThisColors=256; /* Yes, this is in the spec, ugh */
                
-/*             printf("Option: %ix%ix%i ",ThisWidth,ThisHeight,ThisColors);*/
-       
                ThisScore = ThisColors*1024+ThisWidth*ThisHeight; 
 
                if (ThisScore>State->ImageScore) {
                        State->ImageScore = ThisScore;
                        State->DIBoffset = (Ptr[15]<<24)+(Ptr[14]<<16)+
                                           (Ptr[13]<<8) + (Ptr[12]);
-/*                     printf("*");*/
                                                                 
                }
                
-/*             printf("\n");*/
                
                Ptr += 16;      
        } 
@@ -277,22 +261,29 @@ static void DecodeHeader(guchar *Data, gint Bytes,
        
        BIH = Data+State->DIBoffset;
 
-/*     DumpBIH(BIH);*/
+#ifdef DUMPBIH
+       DumpBIH(BIH);
+#endif 
        
        /* Add the palette to the headersize */
                
        State->Header.width =
-           (BIH[7] << 24) + (BIH[6] << 16) + (BIH[5] << 8) + (BIH[4]);
+           (int)(BIH[7] << 24) + (BIH[6] << 16) + (BIH[5] << 8) + (BIH[4]);
        State->Header.height =
-           (BIH[11] << 24) + (BIH[10] << 16) + (BIH[9] << 8) + (BIH[8])/2;
+           (int)(BIH[11] << 24) + (BIH[10] << 16) + (BIH[9] << 8) + (BIH[8])/2;
            /* /2 because the BIH height includes the transparency mask */
        State->Header.depth = (BIH[15] << 8) + (BIH[14]);;
 
-       State->Type = State->Header.depth;      /* This may be less trivial someday */
+       State->Type = State->Header.depth;      
        if (State->Lines>=State->Header.height)
-               State->Type = 1;
+               State->Type = 1; /* The transparency mask is 1 bpp */
+       
        
-       I =(BIH[35] << 24) + (BIH[34] << 16) + (BIH[33] << 8) + (BIH[32]);
+       
+       /* Determine the  palette size. If the header indicates 0, it
+          is actually the maximum for the bpp. You have to love the
+          guys who made the spec. */
+       I =(int)(BIH[35] << 24) + (BIH[34] << 16) + (BIH[33] << 8) + (BIH[32]);
        if ((I==0)&&(State->Type==1))
                I = 2*4;
        if ((I==0)&&(State->Type==4))
@@ -314,13 +305,13 @@ static void DecodeHeader(guchar *Data, gint Bytes,
                g_assert(0); /* Compressed icons aren't allowed */
        }
 
+       /* Negative heights mean top-down pixel-order */
        if (State->Header.height < 0) {
                State->Header.height = -State->Header.height;
                State->Header.Negative = 1;
        }
        if (State->Header.width < 0) {
                State->Header.width = -State->Header.width;
-               State->Header.Negative = 0;
        }
 
        if (State->Type == 24)
@@ -328,9 +319,7 @@ static void DecodeHeader(guchar *Data, gint Bytes,
        if (State->Type == 8)
                State->LineWidth = State->Header.width * 1;
        if (State->Type == 4) {
-               State->LineWidth = State->Header.width/2;
-               if ((State->Header.width & 1) != 0)
-                       State->LineWidth++;
+               State->LineWidth = (State->Header.width+1)/2;
        }
        if (State->Type == 1) {
                State->LineWidth = State->Header.width / 8;
@@ -340,7 +329,7 @@ static void DecodeHeader(guchar *Data, gint Bytes,
 
        /* Pad to a 32 bit boundary */
        if (((State->LineWidth % 4) > 0))
-               State->LineWidth = (State->LineWidth / 3) * 3 + 3;
+               State->LineWidth = (State->LineWidth / 4) * 4 + 4;
 
 
        if (State->LineBuf == NULL)
@@ -538,9 +527,9 @@ static void OneLine1(struct ico_progressive_state *context)
                Bit = (context->LineBuf[X / 8]) >> (7 - (X & 7));
                Bit = Bit & 1;
                /* The joys of having a BGR byteorder */
-               Pixels[X * 4 + 0] = context->HeaderBuf[Bit + 32];
-               Pixels[X * 4 + 1] = context->HeaderBuf[Bit + 2 + 32];
-               Pixels[X * 4 + 2] = context->HeaderBuf[Bit + 4 + 32];
+               Pixels[X * 4 + 0] = Bit*255;
+               Pixels[X * 4 + 1] = Bit*255;
+               Pixels[X * 4 + 2] = Bit*255;
                X++;
        }
 }
@@ -642,7 +631,6 @@ gboolean image_load_increment(gpointer data, guchar * buf, guint size)
        gint BytesToCopy;
 
        while (size > 0) {
-/*             printf("Y=%i  C=%i H=%i\n",context->Lines,context->Type,context->Header.height);*/
                g_assert(context->LineDone >= 0);
                if (context->HeaderDone < context->HeaderSize) {        /* We still 
                                                                           have headerbytes to do */
@@ -651,7 +639,7 @@ gboolean image_load_increment(gpointer data, guchar * buf, guint size)
                        if (BytesToCopy > size)
                                BytesToCopy = size;
 
-                       memcpy(context->HeaderBuf + context->HeaderDone,
+                       memmove(context->HeaderBuf + context->HeaderDone,
                               buf, BytesToCopy);
 
                        size -= BytesToCopy;
@@ -666,7 +654,7 @@ gboolean image_load_increment(gpointer data, guchar * buf, guint size)
                                BytesToCopy = size;
 
                        if (BytesToCopy > 0) {
-                               memcpy(context->LineBuf +
+                               memmove(context->LineBuf +
                                       context->LineDone, buf,
                                       BytesToCopy);
 
index de602b473cf1291dcdab31d585e07e51632f6930..7073134945488da53fd8398904e6b9f76bbe9817 100644 (file)
@@ -71,17 +71,6 @@ static unsigned int be32_to_cpu(guint i)
        return i2;
 }
 
-/* 
-       Destroy notification function for the libart pixbuf 
-*/
-
-static void free_buffer(gpointer user_data, gpointer data)
-{
-       free(data);
-}
-
-
-
 
 /* Progressive loading */
 
@@ -126,7 +115,6 @@ GdkPixbuf *image_load(FILE * f)
        guchar *membuf;
        size_t length;
        struct ras_progressive_state *State;
-       int fd;
        
        GdkPixbuf *pb;
        
@@ -138,7 +126,7 @@ GdkPixbuf *image_load(FILE * f)
        
        while (feof(f) == 0) {
                length = fread(membuf, 1, 4096, f);
-               image_load_increment(State, membuf, length);
+               (void)image_load_increment(State, membuf, length);
        } 
        g_free(membuf);
        if (State->pixbuf != NULL)
@@ -147,7 +135,7 @@ GdkPixbuf *image_load(FILE * f)
        pb = State->pixbuf;
 
        image_stop_load(State);
-       return State->pixbuf;
+       return pb;
 }
 
 static void RAS2State(struct rasterfile *RAS,
@@ -416,7 +404,7 @@ gboolean image_load_increment(gpointer data, guchar * buf, guint size)
                        if (BytesToCopy > size)
                                BytesToCopy = size;
 
-                       memcpy(context->HeaderBuf + context->HeaderDone,
+                       memmove(context->HeaderBuf + context->HeaderDone,
                               buf, BytesToCopy);
 
                        size -= BytesToCopy;
@@ -431,7 +419,7 @@ gboolean image_load_increment(gpointer data, guchar * buf, guint size)
                                BytesToCopy = size;
 
                        if (BytesToCopy > 0) {
-                               memcpy(context->LineBuf +
+                               memmove(context->LineBuf +
                                       context->LineDone, buf,
                                       BytesToCopy);